/******************************************************************************
	File Name:
		UserAMessage.cc
	Description:
		Message System Definition for User A: between A's server and A's Clients.
	History:
		PROGRAMMER		Date			Description			
		Hongqi,Wang		05/31/2009		Original

	Note:
	
******************************************************************************/

const UInt32 UserAMessage::bitMask[32] =
	{
	0x00000001, 0x00000002, 0x00000004, 0x00000008,
	0x00000010, 0x00000020, 0x00000040, 0x00000080,
	0x00000100, 0x00000200, 0x00000400, 0x00000800,
	0x00001000, 0x00002000, 0x00004000, 0x00008000,
	0x00010000, 0x00020000, 0x00040000, 0x00080000,
	0x00100000, 0x00200000, 0x00400000, 0x00800000,
	0x01000000, 0x02000000, 0x04000000, 0x08000000,
	0x10000000, 0x20000000, 0x40000000, 0x80000000
	};

UserAMessage::UserAMessage ( )
	{
	version = USER_A_MSG_CURRENT_VERSION;
	usageBits = 0;
	msgType = 0;
	memset ( &data, 0, sizeof(data) );
	decodeError = False;
	}

UserAMessage::~UserAMessage ( )
	{
	}
	
void UserAMessage::SetField1 ( UInt32 & value )
	{
	data.Field1 = value;
	usageBits |= bitMask[UAM_FIELD1_BIT];
	}
	
void UserAMessage::SetField2 ( UInt32 & value )
	{
	data.Field2 = value;
	usageBits |= bitMask[UAM_FIELD2_BIT];
	}
	
void UserAMessage::SetField3 ( UInt32 & value )
	{
	data.Field3 = value;
	usageBits |= bitMask[UAM_FIELD3_BIT];
	}
	
void UserAMessage::SetField4 ( UInt32 & value )
	{
	data.Field4 = value;
	usageBits |= bitMask[UAM_FIELD4_BIT];
	}

void UserAMessage::SetField5 ( UInt32 & value )
	{
	data.Field5 = value;
	usageBits |= bitMask[UAM_FIELD5_BIT];
	}
	
//------------------------------------------------------------------------
//	Routine Name:	UserAMessage::HasData
//	Purpose:		Test whether the message contains a specific field
//------------------------------------------------------------------------
IBool UserAMessage::HasData ( UserABits fieldId )
	{
	if ( (int)fieldId < 0 || fieldId >= UAM_MAX_BITS ) 
		{
		return False;
		}
	
	if ( ( usageBits & bitMask[fieldId] ) != 0 ) 
		{
		return True;
		}
	
	return False;
	}
	
UInt32 UserAMessage::Sizeof ( ) const
	{
	return sizeof ( UserAMessage ) - sizeof ( Message );
	}
	
UserAMsgVersion UserAMessage::Version ( ) const
	{
	return USER_A_MSG_CURRENT_VERSION;
	}
	
void UserAMessage::EncodeHeader ( MessageBuffer & buffer )
	{
	buffer.Write8( Version( ) );
	buffer.Write32( usageBits );
	buffer.Write32( msgType );
	buffer.WriteGmtTime ( transTime );
	}
	
	
//------------------------------------------------------------------------
//	Routine Name:	UserAMessage::Encode
//	Purpose:		Convert the message to network order with byte packing
//					Fields that do not have values are omitted
//------------------------------------------------------------------------

IStatus UserAMessage::Encode ( void * buffer, int bufferSize )
	{
	int field;
	UInt32 used = usageBits;
	
	MessageBuffer b(buffer, bufferSize);
	
	//...encode header
	EncodeHeader ( b );
	
	//...encode rest of data
	for ( field = 0; field < UAM_MAX_BITS; field++ )
		{
		if ( used & 0x01 )
			{
			switch ( field )
				{
				case UAM_FIELD1_BIT:
					b.Write32 ( data.Field1 );
					break;
				case UAM_FIELD2_BIT:
					b.Write32 ( data.Field2 );
					break;
				case UAM_FIELD3_BIT:
					b.Write32 ( data.Field3 );
					break;
				case UAM_FIELD4_BIT:
					b.Write32 ( data.Field4 );
					break;
				case UAM_FIELD5_BIT:
					b.Write32 ( data.Field5 );
					break;
				default:
					sysLogDebug ( LOG_LEVEL_LOW, "Invalid field %d in UserAMessage::Encode()\n",
							field );
					break;
				}
			}
		used >>= 1;
		}
	if ( b.IsOk( ) ) return AOK;
	else return ERROR;
	}
	
void UserAMessage::DecodeHeader ( void * buffer, int bufferSize )
	{
	MessageBuffer b( buffer, bufferSize );
	DecodeHeader ( b );
	}

	
void UserAMessage::DecodeHeader ( MessageBuffer & buffer )
	{
	version		= buffer.Read8  ( );
	usageBits	= buffer.Read32 ( );
	msgType		= buffer.Read32 ( );
	buffer.ReadGmtTime( transTime );
	}
	
//------------------------------------------------------------------------
//	Routine Name:	UserAMessage::Decode
//	Purpose:		Translate the message from network transmission format
//					to internal format
//------------------------------------------------------------------------
IStatus UserAMessage::Decode ( void * buffer, int bufferSize )
	{
	UInt32 used;
	
	MessageBuffer b(buffer, bufferSize);
	
	//...decode header
	DecodeHeader ( b );
	
	//...decode rest of data
	used = usageBits;
	
	for ( field = 0; field < UAM_MAX_BITS; field++ )
		{
		if ( used & 0x01 )
			{
			switch ( field )
				{
				case UAM_FIELD1_BIT:
					data.Field1 = b.Read32 (  );
					break;
				case UAM_FIELD2_BIT:
					data.Field2 = b.Read32 (  );
					break;
				case UAM_FIELD3_BIT:
					data.Field3 = b.Read32 (  );
					break;
				case UAM_FIELD4_BIT:
					data.Field4 = b.Read32 (  );
					break;
				case UAM_FIELD5_BIT:
					data.Field5 = b.Read32 (  );
					break;
				default:
					sysLogDebug ( LOG_LEVEL_LOW, "Invalid field %d in UserAMessage::Decode()\n",
							field );
					break;
				}
			}
		used >>= 1;
		}
	if ( b.IsOk( ) ) return AOK;
	else return ERROR;
	}
	
